#include "SynchroQueue.h"

SynchroQueue::SynchroQueue()
{
    pthread_mutex_init(&mtxQue, NULL);
    queSize = 0;
    queSizeThreshold = -1;
    sourceIsFinished = false;

    gQueue = gdsl_queue_alloc("QueData", NULL, NULL);
}

SynchroQueue::SynchroQueue(int MaxQueSize)
{
    pthread_mutex_init(&mtxQue, NULL);
    queSize = 0;
    queSizeThreshold = MaxQueSize;
    sourceIsFinished = false;

    gQueue = gdsl_queue_alloc("QueData", NULL, NULL);
}

SynchroQueue::~SynchroQueue()
{
    pthread_mutex_destroy(&mtxQue);

    gdsl_queue_free(gQueue);
}

void SynchroQueue::add(void *data)
{
    // FIXME, this should be done via conditions
    while (queSizeThreshold > 0 && queSize > queSizeThreshold)
    {
        usleep(10);
    }

    pthread_mutex_lock(&mtxQue);
    gdsl_queue_insert(gQueue, data);
    queSize++;
    pthread_mutex_unlock(&mtxQue);
}

bool SynchroQueue::addIfPossible(void *data)
{
    // FIXME, this should be done via conditions
    if (queSizeThreshold > 0 && queSize > queSizeThreshold)
    {
       return false;
    }

    pthread_mutex_lock(&mtxQue);
    gdsl_queue_insert(gQueue, data);
    queSize++;
    pthread_mutex_unlock(&mtxQue);

    return true;
}

void * SynchroQueue::addAndGetIfFull(void *data)
{
    void * res = NULL;

    pthread_mutex_lock(&mtxQue);
    gdsl_queue_insert(gQueue, data);
    queSize++;
    if (queSizeThreshold > 0 && queSize > queSizeThreshold)
    {
        res = gdsl_queue_remove(gQueue);
        queSize--;
    }
    pthread_mutex_unlock(&mtxQue);

    return res;
}

void * SynchroQueue::get()
{
    void *res = NULL;

    pthread_mutex_lock(&mtxQue);
    if (queSize > 0)
    {
        res = gdsl_queue_remove(gQueue);
        queSize--;
    }
    pthread_mutex_unlock(&mtxQue);

    return res;
}

